#print >>sys.stderr, 'got all the way through'
from google.appengine.api import images
from google.appengine.ext import db
import cgi
import os
import wsgiref.handlers
from google.appengine.api import memcache
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.api import urlfetch
import random
import datetime
import sys
import string
import time
from django.utils import simplejson as json

import gviz_api


####### MODELS

class Business(db.Model):   
    cdate = db.DateTimeProperty(auto_now_add=True)
    name = db.StringProperty(required=True)
    manager_list = db.StringListProperty(default=[])  #name|pw
    branch_list = db.StringListProperty(default=[]) #name
    
    #menuitems is here

class Branch(db.Model):   
    #parent is  business
    cdate = db.DateTimeProperty(auto_now_add=True)
    name = db.StringProperty(required=True)
    user_rev = db.IntegerProperty(required=True, default=1) 
    manager_list = db.StringListProperty(default=[])  #name|idcode|idcode pw
    server_list = db.StringListProperty(default=[])  #name|idcode|idcode pw
    kitchen_list = db.StringListProperty(default=[]) #
    
    phone = db.PhoneNumberProperty()
    email = db.EmailProperty()
    address = db.PostalAddressProperty()
    specials = db.StringListProperty(default=[])
    events = db.StringListProperty(default=[]) #dd/mm/yy|description of event
    hours =   db.StringListProperty(default=[]) #branch hours Monday|4am|5pm
    
    menu_rev = db.IntegerProperty(required=True, default=1) 
    menu_items = db.StringListProperty(default=[]) #name|description|price
    menu_catagories = db.StringListProperty(default=[]) #
   
class DataSet(db.Model):   
    #parent is branch or business
    cdate = db.DateTimeProperty(auto_now_add=True)
    data = db.Text()
    
    
class Employee(db.Model):   
    cdate = db.DateTimeProperty(auto_now_add=True)
    name = db.StringProperty(required=True)
    pwcode = db.StringProperty(required=True,default='123')
    idcode = db.StringProperty(required=True,default='111')
    permissions =   db.StringListProperty(default=[]) #possible: view,create,edit
    
    schedule =   db.StringListProperty(default=[]) #branch name|Monday|4am|5pm
    phone = db.PhoneNumberProperty()
    email = db.EmailProperty()
    address = db.PostalAddressProperty()
    
    business = db.ReferenceProperty(Business,
                               required=True,
                               collection_name='employees')
     

class MenuItem(db.Model):   
    cdate = db.DateTimeProperty(auto_now_add=True)
    creator = db.StringProperty(required=True) #name of employee or "admin"
    name = db.StringProperty(required=True)
    menu_description = db.StringProperty() #this is what shows up on the menu
    menu_category = db.StringProperty() #catagory in the menu
    menu_index = db.StringProperty() #index in menu
    
    tax_rate = db.FloatProperty(required=True,default=0.0) #.07
    inventory = db.FloatProperty(required=True,default=0.0) #no clue what this means
    in_use = db.StringProperty(required=True,default='true') #if it is in use
    price_list = db.StringListProperty(default=[]) #mm/dd/yyyy|price
    kitchen = db.StringProperty(required=True,default='default') #which kitchen to send check to
    prep_time = db.FloatProperty(required=True,default=0.0) #how long in minutes to prepare something
    options = db.TextProperty() #there will be some format for rendering options
    
    business = db.ReferenceProperty(Business,
                               required=True,
                               collection_name='menuitems')
    
 
class Customer(db.Model):   
    cdate = db.DateTimeProperty(auto_now_add=True)
    display_name = db.StringProperty(required=True)
    names = db.StringListProperty(default=[]) #list of all the names on the account
    card_data = db.StringProperty() #some string representation of credit card data
    credit_limit = db.FloatProperty(required=True)

    contact_name = db.StringProperty(required=True)
    contact_phone = db.PhoneNumberProperty()
    contact_email = db.EmailProperty()
    
    #checks is here
    #reservations is here
 
class Check(db.Model):   
    cdate = db.DateTimeProperty(auto_now_add=True)
    check_type = db.StringProperty(default='eatin',required=True,choices=set(['eatin','takeout','delivery']) ) 
    created_by = db.StringProperty(required=True) #name of employee or "online"
    created_at = db.IntegerProperty() #this is datetime stamp from computer when it was opened, lets us see if we already have it or not.
    number_guests = db.IntegerProperty() 
    check_owner = db.StringProperty(required=True) #name of employee
    sale_total = db.FloatProperty(required=True,default=0.0) #total price of all items
    paid_total = db.FloatProperty(required=True,default=0.0) #total amount paid
    gratuity = db.FloatProperty(required=True,default=0.0) #dollars of tip
    killed_by = db.StringProperty(default='') #name of employee
    killed_at = db.IntegerProperty(default=0)
    table_number = db.StringProperty(required=False) #name of employee
    
    pickup_time = db.StringProperty() #some sort of date and time
    edit_list = db.StringListProperty(default=[]) #date|employeename|propertyname|oldvalue|newvalue

    check_rev = db.IntegerProperty(required=True, default=1)
    check_log = db.StringListProperty(default=['sale_total:0:0:admin']) #this is a list of the changes for each rev bump, format is  property:newvalue|property:newvalue
    
    customer = db.ReferenceProperty(Customer,
                               required=False,
                               collection_name='checks')
    branch = db.ReferenceProperty(Branch,
                               required=True,
                               collection_name='checks')
    
class ItemOrder(db.Model):   
    #parent is check
    cdate = db.DateTimeProperty(auto_now_add=True)
    item_name = db.StringProperty(required=True) #name of Menu_Item
    price = db.FloatProperty(required=True) #price of one item
    quantity = db.IntegerProperty(required=True) 
    ordered_by = db.StringProperty(required=True) #name of employee
    ordered_at = db.IntegerProperty() #time when ordre is sent to the kitchen
    ordered_from = db.StringProperty(required=False) #name of kitchen
    ready_at = db.IntegerProperty() #time when this item is ready
    edit_list = db.StringListProperty(default=[]) #date|employeename|propertyname|oldvalue|newvalue
    options = db.StringListProperty(default=[]) #list of options for menu item
    discount_rate = db.FloatProperty(required=True,default=0.0) #.08 for 8% discount
    invalid = db.StringProperty(required=True,default='false') #if it is in use
    
    itemo_rev = db.IntegerProperty(required=True, default=1)
    itemo_log = db.StringListProperty(default=['rev:1:1:admin']) #some log of edits
    
class Payment(db.Model):   
    #parent is check
    cdate = db.DateTimeProperty(auto_now_add=True)
    amount = db.FloatProperty(required=True) #payment amount
    gratuity = db.FloatProperty(required=True) #payment amount
    check_type = db.StringProperty(default='visa',required=True,choices=set(['visa','cash','check']) ) 
    

class Reservation(db.Model):   
    #parent is check
    cdate = db.DateTimeProperty(auto_now_add=True)
    reservation_type = db.StringProperty(default='waitlist',required=True,choices=set(['waitlist','reservation']) ) 
    name = db.StringProperty(required=True) #name of party
    number_guests = db.IntegerProperty() 
    reservation_time = db.IntegerProperty() #time when party desires to be seated
    preferences = db.StringProperty()  #notes on any special preferences
    quoted_waittime = db.IntegerProperty() #minutes party was told wait would be
    seated_at = db.IntegerProperty() #time when party was seated

    customer = db.ReferenceProperty(Customer,
                               required=True,
                               collection_name='reservations')


class Check2(db.Model):   
    #key  name
    cdate = db.DateTimeProperty(auto_now_add=True)
    checktime = db.StringProperty(required=True)
    name = db.StringProperty(required=True)
    pay_type = db.StringProperty(default='cash',required=True,choices=set(['cash','visa','check']) ) 
    total = db.FloatProperty(required=True,default=0.0)
    items = db.StringListProperty(default=[])  #list of all item names
    checkkey = db.IntegerProperty()
    
  
class MenuItem2(db.Model):   
    #key  name
    cdate = db.DateTimeProperty(auto_now_add=True)
    name = db.StringProperty(required=True)
    price = db.FloatProperty(required=True,default=0.0)
    category = db.StringProperty(required=False)
  
  
class Location2(db.Model):   
    #key  name
    cdate = db.DateTimeProperty(auto_now_add=True)
    name = db.StringProperty(required=True)
    price = db.FloatProperty(required=True,default=0.0)
    category = db.StringProperty(required=False)  
  
############################################
############################################  
#TOOLS
def fix_names(data):
    for i in ['bsname','brname','ename','miname','creator']:
        if data.has_key(i):
            data[i] = data[i].lower().strip(' ')
    return data
  
def get_business(data):
    bs = db.GqlQuery("SELECT * FROM Business WHERE name = :1",data['bsname']).fetch(1)
    if bs == []: return []
    else: return bs[0]
  
def get_branch(data):
    br_name = data['brname']
    bs = get_business(data)
    if bs == []: return [],[] 
    br = db.GqlQuery("SELECT * FROM Branch WHERE name = :1 AND ANCESTOR IS :2",br_name,bs.key()).fetch(1) 
    if br: return br[0],bs
    else: return [],bs
    
#USER ACTIONS
def station_open(data):
    #brname,bsname,pin
    br,bs = get_branch(data)
    if br==[] or bs==[]:return {'success':False,'msg':'Branch doesnt exist'}
    for man in br.manager_list:
        ml = man.split('|')
        if data['pin']==ml[2]: return {'success':True,'bs_name':data['bsname'],'br_name':data['brname'],'e_name':ml[0],'e_idcode':ml[1]}
    else:return {'success':False,'msg':'Can not find you as a manager'}
   

def station_login(data):
    #brname,bsname,pin
    br,bs = get_branch(data)
    if br==[] or bs==[]:return {'success':False,'msg':'Branch doesnt exist'}
    for man in br.manager_list+br.server_list:
        ml = man.split('|')
        if data['pin']==ml[2]: return {'success':True,'bs_name':data['bsname'],'br_name':data['brname'],'e_name':ml[0],'e_idcode':ml[1]}
    else:return {'success':False,'msg':'Can not find you as a manager or server'}

    
def local_sync(data):
    #brname,bsname,user_rev,menu_rev,local_state
    br,bs = get_branch(data)

    checks_upt = {'remove':[],'new':[],'update':[], 'errors':[] }
    itemso_upt = {'remove':[],'new':[],'update':[], 'errors':[]}
    out = {'success':True,'menu':[],'users':[]}
    if br==[] or bs==[]:return {'success':False,'msg':'Branch doesnt exist'}
    if br.menu_rev != data['menu_rev']: out['menu']=[i.split('|') for i in br.menu_items]
    if br.user_rev != data['user_rev']: out['users']=[i.split('|') for i in br.manager_list+br.server_list]
    
    #local_state = {'current':{checkID:[rev,{itemoID:rev}]}, 'edit':{'checks':[id, 'property:newvalue|property:newvalue']  ,'itemso':[id,'property:newvalue|property:newvalue']},'new':{'checks':[whole dict from check]  ,'itemso':[whole dict from items]}}
    #take all new items, add to datastore
    for i in data['local_state']['new']['checks']:
        add_check(br,i)
    for i in data['local_state']['new']['itemso']:
        chk = db.GqlQuery("SELECT * FROM Check WHERE created_at = :1 AND branch = :2",i['checkid'],br.key()).fetch(3)
        #print >>sys.stderr, str(chk)
        if chk: add_itemorder(chk[0].key(),i)
    
    #bringing up edits from local
    for i in data['local_state']['edit']['checks']:
        checks_upt['errors'].append( edit_check(br,i))
    for i in data['local_state']['edit']['itemso']:
        itemso_upt['errors'].append(edit_itemorder(br,i))
    
    
    
    #check all stuff in memory for new revs, and send them down if they exist
    
    for chk,id in data['local_state']['current'].items():
        chk = int(chk)
        c = db.GqlQuery("SELECT * FROM Check WHERE created_at = :1 AND branch = :2",chk,br.key()).fetch(3)[0]
        if c.check_rev == id[0]: continue
        chngs = [['rev',c.check_rev,c.check_rev,'admin']]
        for i in c.check_log[id[0]:c.check_rev]:
            for cupt in i.split('|'):
                chngs.append(cupt.split(':'))
        checks_upt['update'].append([chk,chngs])
        
       # elif id[0]==0:  #this is if we just added the check
         #   if c.check_rev >= 1 and c.check_log ==[]: checks_upt['update'].append([chk,[['rev',c.check_rev],['sale_total',c.sale_total]]])
            
        #print >>sys.stderr, str(id[1])
        for io,iorev in id[1].items():
            io = int(io)
            itemo = db.GqlQuery("SELECT * FROM ItemOrder WHERE ordered_at = :1 AND ANCESTOR IS :2",io,c.key()).fetch(3)[0]
            if itemo.itemo_rev == iorev: continue
            
            chngs = [['rev',itemo.itemo_rev,itemo.itemo_rev,'admin']]
            for i in itemo.itemo_log[iorev:itemo.itemo_rev]:
                for cupt in i.split('|'):
                    chngs.append(cupt.split(':'))
            itemso_upt['update'].append([io,chngs])
            
            #elif iorev==0 and itemo.itemo_log==[]:  #this is if we just added the check
            #    itemso_upt['update'].append([io,[['rev',itemo.itemo_rev]]])
            
            
            
        #find if there were new items for this check
        newio = db.GqlQuery("SELECT * FROM ItemOrder WHERE ANCESTOR IS :1",c.key()).fetch(50)
        #print >>sys.stderr, id[1].keys()
        local_ios = [int(i) for i in id[1].keys()]
        for nio in [k for k in newio if k.ordered_at not in local_ios]:
            #print >>sys.stderr, nio.ordered_at
            #ordered_at INTEGER,ordered_by TEXT,name TEXT, price REAL, quantity INTEGER, checkid INTEGER,rev INTEGER,local_edit INTEGER)
            itemso_upt['new'].append([nio.ordered_at ,nio.ordered_by ,nio.item_name , nio.price , nio.quantity , c.created_at ,nio.itemo_rev ,''])
    
    #find all the checks that are not in the local db and send them down
    nchk = db.GqlQuery("SELECT * FROM Check WHERE killed_at = :1 AND branch = :2",0,br.key()).fetch(100)
    local_chks = [int(i) for i in data['local_state']['current'].keys()]
    for nc in [k for k in nchk if k.created_at not in local_chks]:
        #created_at INTEGER,created_by TEXT, killed_at INTEGER, killed_by TEXT,rev INTEGER,local_edit INTEGER,sale_total REAL
        checks_upt['new'].append([nc.created_at,nc.created_by, nc.killed_at, nc.killed_by ,nc.check_rev ,'' ,nc.sale_total,nc.number_guests ])
        newio = db.GqlQuery("SELECT * FROM ItemOrder WHERE ANCESTOR IS :1",nc.key()).fetch(50)
        for nio in newio:
            #ordered_at INTEGER,ordered_by TEXT,name TEXT, price REAL, quantity INTEGER, checkid INTEGER,rev INTEGER,local_edit INTEGER)
            itemso_upt['new'].append([nio.ordered_at ,nio.ordered_by ,nio.item_name , nio.price , nio.quantity , nc.created_at ,nio.itemo_rev ,''])
    
    
    #checks_upt = {'remove':[list of IDs to remove],'new':[full data that we can just plug in],  'update':[[checkID,[[variable,newvalue],[variable2,value]] ],........] }
    #            itemso_upt = same as above
    out['checks_upt']=checks_upt
    out['itemso_upt']=itemso_upt
    return out

#CREATE
def add_business(data):  
    #bsname,
    bs_name = data['bsname']
    bs = get_business(data)
    if bs != []: return {'success':False,'msg':'Business already exists'} 
    Business(name = bs_name).put()
    return {'success':True}
def add_branch(data):
    #brname,bsname
    br,bs = get_branch(data)
    if bs == []: return {'success':False,'msg':'Could not find Business'} 
    if br != []: return {'success':False,'msg':'Branch already exists'} 
    Branch(parent=bs,
            name = data['brname']).put()
    bs.branch_list.append(data['brname'])
    bs.put()
    return {'success':True}
def add_employee(data):
    #ename,brname,bsname,idcode,pwcode,permissions,emptype
    br,bs = get_branch(data)
    if not br: return {'success':False,'msg':'Branch not found'} 
    emp = db.GqlQuery("SELECT * FROM Employee WHERE idcode = :1 AND business = :2",data['idcode'],bs.key()).count()
    if emp!=0: return {'success':False,'msg':'Employee Idcode already exists '+data['idcode']} 
    try:
        q = int(data['idcode'])
        q = int(data['pwcode'])
    except:return {'success':False,'msg':'Idcode and pw must be only numbers'}
    if type(data['permissions']) != type([]): return {'success':False,'msg':'permissions must be a list'}
    Employee(name = data['ename'],
            pwcode=data['pwcode'],
            idcode=data['idcode'],
            permissions=data['permissions'],
            business=bs).put()
    tmp = '%s|%s|%s%s'%(data['ename'],data['idcode'],data['idcode'],data['pwcode'])
    if data['emptype'] == 'manager': br.manager_list.append(tmp)
    else:br.server_list.append(tmp)
    br.put()
    return {'success':True}
def add_menuitem(data):
    #miname,creator,brname,bsname,description,price
    br,bs = get_branch(data)
    if not br: return {'success':False,'msg':'Branch not found'} 
    mi = db.GqlQuery("SELECT * FROM MenuItem WHERE name = :1 AND creator = :2 AND business = :3",
                                                data['miname'],data['creator'],bs.key()).count()
    if mi!=0: return {'success':False,'msg':'That MenuItem already exists'} 
    try:price = float(data['price'])
    except:return {'success':False,'msg':'price must be a float'}

    dt = datetime.datetime.now().strftime('%m/%d/%Y')
    mi = MenuItem(name = data['miname'],
            creator=data['creator'],
            menu_description=data['description'],
            price_list = ['%s|%.02f'%(dt,price)],
            business=bs)
    mi.put()
            
    tmp = '%s|%s|%s|%.02f'%(mi.key(),data['miname'],data['description'],price)
    br.menu_items.append(tmp)
    br.put()
    return {'success':True}

def add_check(br,data):
    #created_at,created_by
    chk = db.GqlQuery("SELECT * FROM Check WHERE created_at = :1 AND branch = :2",data['created_at'],br.key()).count()
    if chk!=0: return False 
    Check(created_by = data['created_by'],
            check_owner = data['created_by'],
            created_at=data['created_at'],
            number_guests=data['number_guests'],
            branch=br).put()
            
    return True

def add_itemorder(check_key,data):
    #ordered_at ,ordered_by ,name , price , quantity
    io = db.GqlQuery("SELECT * FROM ItemOrder WHERE ordered_at = :1 AND ANCESTOR IS :2",data['ordered_at'],check_key).count()
    if io!=0: return False 
    
    def txn():
        chk = db.get(check_key)
        if not chk: return False
        else:
            ItemOrder(parent=chk,
                    item_name = data['name'],
                    price = float(data['price']),
                    quantity = int(data['quantity']),
                    ordered_by = data['ordered_by'],
                    ordered_at = data['ordered_at']).put()
            chk.sale_total += float(data['price'])*int(data['quantity'])
            chk.check_rev +=1
            chk.check_log.append('sale_total:0:%s:admin'%(chk.sale_total))
            chk.put()
            return True
    output = db.run_in_transaction(txn)
    return output
    
def edit_check(br,edit_info):
    #id, 'property:newvalue|property:newvalue']
    chk = db.GqlQuery("SELECT * FROM Check WHERE created_at = :1 AND branch = :2",edit_info[0],br.key()).fetch(5)
    if len(chk)==0: return [] 
    c = chk[0]
    logmsg = []
    errors = []
    for i in edit_info[1].strip('|').split('|'):
        d = i.split(':')
        if d[0]=='killed_by':
            if c.killed_by != d[1]: 
                errors.append(i)
                continue
            else:c.killed_by = d[2]
        elif d[0]=='killed_at':
            if c.killed_at != int(d[1]): 
                errors.append(i)
                continue
            else:c.killed_at = int(d[2])
        elif d[0]=='number_guests':
            if c.number_guests != int(d[1]): 
                errors.append(i)
                continue
            else:c.number_guests = int(d[2])
        
        else: continue
        logmsg.append(i)
    if logmsg:
        c.check_rev +=1
        c.check_log.append('|'.join(logmsg))
        c.put()
    print >>sys.stderr, str(errors),str(logmsg)
            
    return [c.created_at,errors]

    
def edit_itemorder(br,edit_info):
    pass











#EDIT  
  
  
  
#GET INFO
def get_businesses_info(data):
    bss = db.GqlQuery("SELECT * FROM Business")
    bdict = {}
    for bs in bss:
        bdict[bs.name]=bs.branch_list
    return {'success':True,'businesses_info':bdict}
        
  
  
  
  
  
  
  
  
  
class check12 (webapp.RequestHandler):
    '''
    This is for all the ajax
    '''
    def get(self):
        
    
        template_values = {}
        path = os.path.join(os.path.dirname(__file__), 'webcachetool.html')
        self.response.out.write(template.render(path, template_values))
        
    def post(self):
        pass
        
class POS (webapp.RequestHandler):
    '''
    This is for all the ajax
    '''
    def get(self):
        
    
        template_values = {}
        path = os.path.join(os.path.dirname(__file__), 'html/pos.html')
        self.response.out.write(template.render(path, template_values))
        
    def post(self):
        pass
        
class RPC (webapp.RequestHandler):
    '''
    This is for all the ajax
    '''
    def get(self):
        pass
        
    def post(self):
        action = self.request.get('action')
        data = json.loads(self.request.get('data'))
        data = fix_names(data)
        output = {'success':False,'msg':'No action mathes that'}
        
        
        
        if action=='add_item':   #add user
            #name,price
            name = data['name'].lower().strip(' ')
            mitem = MenuItem.get_by_key_name(name)
            if mitem:
                output = {'success':False,'msg':'already have an item named that, try again'}
            else:
                price = float(data['price'].replace('$','').replace(',',''))
                MenuItem(key_name=name,
                                name=name,
                                price = price).put()
                items = MenuItem.all().fetch(10)
                datai = []
                for i in items:
                    datai.append([i.name,i.price])
                output = {'success':True,'items':datai}
         
        elif action=='add_business':   output = add_business(data)
        elif action=='add_branch':   output = add_branch(data)
        elif action=='add_employee':   output = add_employee(data)
        elif action=='add_menuitem':   output = add_menuitem(data)
        elif action=='add_itemorder':   output = add_itemorder(data)
       

        elif action=='get_businesses_info':   output = get_businesses_info(data)
        elif action=='station_open': output = station_open(data)
        elif action=='station_login': output = station_login(data)
        elif action=='local_sync': output = local_sync(data)
        
        elif action=='sync_checks':   #add user
            #checks
            #CheckTime , Name , Total , pay_type  items ,checkKey 
            out = []
            cd = data['checks']
            for c in cd[1:]:
                ckey = random.randint(100, 1000)
                try: tot = float(c[2])
                except: tot = 0.0
                Check(checktime = c[0],
                        name = c[1],
                        total = tot,
                        items =  c[4].split(','),
                        checkkey = ckey).put()
                out.append([ckey,c[0]])
                
            
                
            output = {'success':True,'checks':out}
        
        
        
        elif action=='get_data':   #add user
            #name,price
            items = MenuItem.all().fetch(10)
            datai = []
            for i in items:
                datai.append([i.name,i.price])
            
            checks = Check.all().fetch(10)
            datac = []
            for i in checks:
                datac.append([i.name,i.total,i.items])
            
            output = {'success':True,'items':datai,'checks':datac}
        
        if action=='ping':   #ping
            output = {'success':True}

        output=json.dumps(output)
        self.response.out.write(output) 
            
class Online (webapp.RequestHandler):
    '''
    This is for all the ajax
    '''
    def get(self):
        template_values = {}
        path = os.path.join(os.path.dirname(__file__), 'html/online.html')
        self.response.out.write(template.render(path, template_values))
        
    def post(self):
        pass           

class Online2 (webapp.RequestHandler):
    '''
    This is for all the ajax
    '''
    def get(self):
        template_values = {}
        path = os.path.join(os.path.dirname(__file__), 'html/online2.html')
        self.response.out.write(template.render(path, template_values))
        
    def post(self):
        pass          

class Welcome (webapp.RequestHandler):
    '''
    This is for all the ajax
    '''
    def get(self):
        template_values = {}
        path = os.path.join(os.path.dirname(__file__), 'html/Welcome.html')
        self.response.out.write(template.render(path, template_values))
        
    def post(self):
        pass          

    
class DataS(webapp.RequestHandler): 
    def get(self): 
        description = {"name": ("string", "Name"),
           "salary": ("number", "Salary"),
           "full_time": ("boolean", "Full Time Employee")}
        data = [{"name": "Mike", "salary": (10000, "$10,000"), "full_time": True},
                {"name": "Jim", "salary": (800, "$800"), "full_time": False},
                {"name": "Alice", "salary": (12500, "$12,500"), "full_time": True},
                {"name": "Bob", "salary": (7000, "$7,000"), "full_time": True}]

        data_table = gviz_api.DataTable(description)
        data_table.LoadData(data)
        self.response.out.write(data_table.ToJSonResponse(columns_order=("name", "salary", "full_time"),order_by="salary"))         
        
        
        
        
        
        
        
        
        
def real_main():
    application = webapp.WSGIApplication(
                                            [
                                            ('/', Welcome),
                                             ('/rpc', RPC),
                                             ('/pos', POS),
                                             ('/online', Online),
                                             ('/online2', Online2),
                                                ],
                                            debug=True)
    wsgiref.handlers.CGIHandler().run(application)
def profile_main():
    # This is the main function for profiling 
    # We've renamed our original main() above to real_main()
    import cProfile, pstats
    prof = cProfile.Profile()
    prof = prof.runctx("real_main()", globals(), locals())
    print "<pre>"
    stats = pstats.Stats(prof)
    stats.sort_stats("time")  # Or cumulative
    stats.print_stats(80)  # 80 = how many to print
    # The rest is optional.
    # stats.print_callees()
    # stats.print_callers()
    print "</pre>"
if __name__ == "__main__":
    real_main()
